<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: discuz_admincp.php 31471 2012-08-31 07:33:26Z zhengqingpeng $
 */
if (!defined('IN_DISCUZ')) {
    exit('Access Denied');
}

class discuz_admincp {

    var $core = null;
    var $script = null;
    var $userlogin = false;
    var $adminsession = array();
    var $adminuser = array();
    var $perms = null;
    var $panel = 1;
    var $isfounder = false;
    var $cpsetting = array();
    var $cpaccess = 0;
    var $sessionlife = 1800;
    var $sessionlimit = 0;

    function &instance() {
        static $object;
        if (empty($object)) {
            $object = new discuz_admincp();
        }
        return $object;
    }

    function __construct() {
        ;
    }

    function init() {

        if (empty($this->core) || !is_object($this->core)) {
            exit('No Discuz core found');
        }

        $this->cpsetting = $this->core->config['admincp'];
        $this->adminuser = & $this->core->var['member'];

        $this->isfounder = $this->checkfounder($this->adminuser);

        $this->sessionlimit = TIMESTAMP - $this->sessionlife;

        $this->check_cpaccess();

        $this->writecplog();
    }

    function writecplog() {
        global $_G;
        $extralog = implodearray(array('GET' => $_GET, 'POST' => $_POST), array('formhash', 'submit', 'addsubmit', 'admin_password', 'sid', 'action'));
        writelog('cplog', implode("\t", clearlogstring(array($_G['timestamp'], $_G['username'], $_G['adminid'], $_G['clientip'], getgpc('action'), $extralog))));
    }

    function check_cpaccess() {

        global $_G;
        $session = array();

        if (!$this->adminuser['uid']) {
            $this->cpaccess = 0;
        } else {

            if (!$this->isfounder) {
                $session = C::t('common_admincp_member')->fetch($this->adminuser['uid']);
                if ($session) {
                    $session = array_merge($session, C::t('common_admincp_session')->fetch($this->adminuser['uid'], $this->panel));
                }
            } else {
                $session = C::t('common_admincp_session')->fetch($this->adminuser['uid'], $this->panel);
            }

            if (empty($session)) {
                $this->cpaccess = $this->isfounder ? 1 : -2;
            } elseif ($_G['setting']['adminipaccess'] && !ipaccess($_G['clientip'], $_G['setting']['adminipaccess'])) {
                $this->do_user_login();
            } elseif ($session && empty($session['uid'])) {
                $this->cpaccess = 1;
            } elseif ($session['dateline'] < $this->sessionlimit) {
                $this->cpaccess = 1;
            } elseif ($this->cpsetting['checkip'] && ($session['ip'] != $this->core->var['clientip'])) {
                $this->cpaccess = 1;
            } elseif ($session['errorcount'] >= 0 && $session['errorcount'] <= 3) {
                $this->cpaccess = 2;
            } elseif ($session['errorcount'] == -1) {
                $this->cpaccess = 3;
            } else {
                $this->cpaccess = -1;
            }
        }

        if ($this->cpaccess == 2 || $this->cpaccess == 3) {
            if (!empty($session['customperm'])) {
                $session['customperm'] = dunserialize($session['customperm']);
            }
        }

        $this->adminsession = $session;

        if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['admin_password'])) {
            if ($this->cpaccess == 2) {
                $this->check_admin_login();
            } elseif ($this->cpaccess == 0) {
                $this->check_user_login();
            }
        }

        if ($this->cpaccess == 1) {
            C::t('common_admincp_session')->delete($this->adminuser['uid'], $this->panel, $this->sessionlife);
            C::t('common_admincp_session')->insert(array(
                'uid' => $this->adminuser['uid'],
                'adminid' => $this->adminuser['adminid'],
                'panel' => $this->panel,
                'ip' => $this->core->var['clientip'],
                'dateline' => TIMESTAMP,
                'errorcount' => 0,
            ));
        } elseif ($this->cpaccess == 3) {
            $this->load_admin_perms();
            C::t('common_admincp_session')->update($this->adminuser['uid'], $this->panel, array('dateline' => TIMESTAMP, 'ip' => $this->core->var['clientip'], 'errorcount' => -1));
        }

        if ($this->cpaccess != 3) {
            $this->do_user_login();
        }
    }

    function check_admin_login() {
        global $_G;
        if ((empty($_POST['admin_questionid']) || empty($_POST['admin_answer'])) && ($_G['config']['admincp']['forcesecques'] || $_G['group']['forcesecques'])) {
            $this->do_user_login();
        }
        loaducenter();
        $ucresult = uc_user_login($this->adminuser['uid'], $_POST['admin_password'], 1);
        if ($ucresult['status'] > 0) {
            C::t('common_admincp_session')->update($this->adminuser['uid'], $this->panel, array('dateline' => TIMESTAMP, 'ip' => $this->core->var['clientip'], 'errorcount' => -1));
            dheader('Location: ' . ADMINSCRIPT . '?' . cpurl('url', array('sid')));
        } else {
            $errorcount = $this->adminsession['errorcount'] + 1;
            C::t('common_admincp_session')->update($this->adminuser['uid'], $this->panel, array('dateline' => TIMESTAMP, 'ip' => $this->core->var['clientip'], 'errorcount' => $errorcount));
        }
    }

    function check_user_login() {
        global $_G;
        $admin_username = isset($_POST['admin_username']) ? trim($_POST['admin_username']) : '';
        if ($admin_username != '') {

            require_once libfile('function/member');
            if (logincheck($_POST['admin_username'])) {
                if ((empty($_POST['admin_questionid']) || empty($_POST['admin_answer'])) && ($_G['config']['admincp']['forcesecques'] || $_G['group']['forcesecques'])) {
                    $this->do_user_login();
                }
                $result = userlogin($_POST['admin_username'], $_POST['admin_password'], $_POST['admin_questionid'], $_POST['admin_answer'], 'username', $this->core->var['clientip']);
                if ($result['status'] == 1) {
                    $cpgroupid = C::t('common_admincp_member')->fetch($result['member']['uid']);
                    $cpgroupid = $cpgroupid['uid'];
                    if ($cpgroupid || $this->checkfounder($result['member'])) {
                        C::t('common_admincp_session')->insert(array(
                            'uid' => $result['member']['uid'],
                            'adminid' => $result['member']['adminid'],
                            'panel' => $this->panel,
                            'dateline' => TIMESTAMP,
                            'ip' => $this->core->var['clientip'],
                            'errorcount' => -1), false, true);

                        setloginstatus($result['member'], 0);
                        dheader('Location: ' . ADMINSCRIPT . '?' . cpurl('url', array('sid')));
                    } else {
                        $this->cpaccess = -2;
                    }
                } else {
                    loginfailed($_POST['admin_username']);
                }
            } else {
                $this->cpaccess = -4;
            }
        }
    }

    function allow($action, $operation, $do) {

        if ($this->perms === null) {
            $this->load_admin_perms();
        }

        if (isset($this->perms['all'])) {
            return $this->perms['all'];
        }

        if (!empty($_POST) && !array_key_exists('_allowpost', $this->perms) && $action . '_' . $operation != 'misc_custommenu') {
            return false;
        }
        $this->perms['misc_custommenu'] = 1;

        $key = $action;
        if (isset($this->perms[$key])) {
            return $this->perms[$key];
        }
        $key = $action . '_' . $operation;
        if (isset($this->perms[$key])) {
            return $this->perms[$key];
        }
        $key = $action . '_' . $operation . '_' . $do;
        if (isset($this->perms[$key])) {
            return $this->perms[$key];
        }
        return false;
    }

    function load_admin_perms() {

        $this->perms = array();
        if (!$this->isfounder) {
            if ($this->adminsession['cpgroupid']) {
                foreach (C::t('common_admincp_perm')->fetch_all_by_cpgroupid($this->adminsession['cpgroupid']) as $perm) {
                    if (empty($this->adminsession['customperm'])) {
                        $this->perms[$perm['perm']] = true;
                    } elseif (!in_array($perm['perm'], (array) $this->adminsession['customperm'])) {
                        $this->perms[$perm['perm']] = true;
                    }
                }
            } else {
                $this->perms['all'] = true;
            }
        } else {
            $this->perms['all'] = true;
        }
    }

    function checkfounder($user) {

        $founders = str_replace(' ', '', $this->cpsetting['founder']);
        if (!$user['uid'] || $user['groupid'] != 1 || $user['adminid'] != 1) {
            return false;
        } elseif (empty($founders)) {
            return true;
        } elseif (strexists(",$founders,", ",$user[uid],")) {
            return true;
        } elseif (!is_numeric($user['username']) && strexists(",$founders,", ",$user[username],")) {
            return true;
        } else {
            return FALSE;
        }
    }

    function do_user_login() {
        require $this->admincpfile('login');
    }

    function do_admin_logout() {
        C::t('common_admincp_session')->delete($this->adminuser['uid'], $this->panel, $this->sessionlife);
    }

    function admincpfile($action) {
        return './source/admincp/admincp_' . $action . '.php';
    }

    function show_admincp_main() {
        $this->do_request('main');
    }

    function show_no_access() {
        cpheader();
        cpmsg('action_noaccess', '', 'error');
        cpfooter();
    }

    function do_request($action) {

        global $_G;

        $lang = lang('admincp');
        $title = 'cplog_' . getgpc('action') . (getgpc('operation') ? '_' . getgpc('operation') : '');
        $operation = getgpc('operation');
        $do = getgpc('do');
        $sid = $_G['sid'];
        $isfounder = $this->isfounder;
        if ($action == 'main' || $this->allow($action, $operation, $do)) {
            require './source/admincp/admincp_' . $action . '.php';
        } else {
            cpheader();
            cpmsg('action_noaccess', '', 'error');
        }
    }

}
